/*
 * Copyright 2023-2024, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Haiku Development Team
 */

#include <arch/timer.h>
#include <boot/kernel_args.h>
#include <kernel.h>
#include <debug.h>
#include <timer.h>
#include <arch/loongarch64/arch_cpu.h>

// 定义调试输出宏
#define TRACE_TIMER
#ifdef TRACE_TIMER
#define TRACE(x...) dprintf("arch_timer: " x)
#else
#define TRACE(x...) ;
#endif

// 龙芯3A6000定时器相关常量
#define LOONGARCH_STABLE_COUNTER_FREQ 100000000 // 稳定计数器频率（100MHz）

// 定时器CSR寄存器地址
#define CSR_TMID 0x40 // 定时器ID
#define CSR_TCFG 0x41 // 定时器配置
#define CSR_TVAL 0x42 // 定时器初值
#define CSR_CNTC 0x43 // 计数器补偿值

// 定时器配置位
#define TCFG_EN (1 << 0)     // 定时器使能
#define TCFG_PERIOD (1 << 1) // 周期性模式
#define TCFG_INT_EN (1 << 2) // 中断使能

// 定时器中断号
#define TIMER_IRQ 10

// 全局变量
static uint64 sTimerConversionFactor;

void arch_timer_set_hardware_timer(bigtime_t timeout)
{
    // 将微秒转换为定时器计数值
    uint64 scaledTimeout = (static_cast<__uint128_t>(timeout) * sTimerConversionFactor) >> 32;

    // 设置定时器初值
    // 注意：龙芯定时器是向下计数的，当计数到0时触发中断
    asm volatile("csrwr %0, %1" : : "r"(scaledTimeout), "i"(CSR_TVAL));

    // 配置并启用定时器
    uint64 tcfg = TCFG_EN | TCFG_INT_EN;
    asm volatile("csrwr %0, %1" : : "r"(tcfg), "i"(CSR_TCFG));

    TRACE("Set hardware timer: %" B_PRId64 " us, scaled: %" B_PRIu64 "\n", timeout, scaledTimeout);
}

void arch_timer_clear_hardware_timer(void)
{
    // 禁用定时器
    asm volatile("csrwr $zero, %0" : : "i"(CSR_TCFG));

    TRACE("Cleared hardware timer\n");
}

int arch_init_timer(kernel_args *args)
{
    // 初始化定时器转换因子
    // 这个因子用于将微秒转换为定时器计数值
    sTimerConversionFactor = (1LL << 32) * 1000000LL / LOONGARCH_STABLE_COUNTER_FREQ;

    // 禁用定时器，确保干净的初始状态
    arch_timer_clear_hardware_timer();

    TRACE("Timer initialized, conversion factor: %" B_PRIu64 "\n", sTimerConversionFactor);

    return B_OK;
}